#include <iostream>
#include <stddef.h>
#include "Game.h"

using namespace std;

Game::Game(Player* player1, Player* player2, Board* board) :
		mPlayers(NULL), mListener(NULL), mPrePass(false), mBoard(NULL) {
	if (board == NULL) {
		mBoard = new Board();
	} else {
		mBoard = board;
	}
	mPlayers = new Player*[2];
	mPlayers[0] = player1;
	mPlayers[0]->setColor(Stone::BLACK);
	mPlayers[1] = player2;
	mPlayers[1]->setColor(Stone::WHITE);
	init();
}

Game::~Game() {
	delete mBoard;
	mBoard = NULL;
}

void Game::init() {
	for (int i = 0; i < 2; i++) {
		mPlayers[i]->setBoard(mBoard);
	}
}

void Game::setListener(IOnGameListener* listener) {
	mListener = listener;
}

void Game::start() {
	try {
		play();
	} catch (GameException e) {
		if (mListener != NULL) {
			mListener->onGiveUp(e.getPlayer());
		}
	}
}

void Game::play() {
	if (mListener != NULL) {
		mListener->onStart(mBoard);
	}
	bool prePass = false;
	while (true) {
		if (isOver()) {
			break;
		}
		Player* player = mPlayers[mBoard->getTurnCount() % 2];
		bool pass = playNext(player);

		if (pass && prePass) {
			break;
		}
		prePass = pass;
	}
	mBoard->mCompleted = true;
	if (mListener != NULL) {
		mListener->onComplete(mBoard);
	}
}

Board::State* Game::getState() {
	return mBoard->getState();
}

bool Game::isOver() {
	return mBoard->isFull();
}

bool Game::playNext(Player* player) {
	Cell* cell = player->next();
	if (cell == Cell::GIVE_UP) {
		throw GameException(player);
	}

	mBoard->putStone(cell, player->getColor());
	if (mListener != NULL) {
		mListener->onPutStone(player, mBoard, cell);
	}

	if (cell == NULL) {
		return true;
	} else {
		return false;
	}
}

